package com.woniuxy.gobang.ui;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;

/**
 * 单机模式窗口及功能
 * 
 * @author AC
 *
 */
public class SingleModeStage extends Stage {
	// 棋盘边距
	private int margin;
	// 棋盘格子大小
	private int size;
	// 格子数
	private int cellCount;
	// 按键区域大小
	private int buttonArea;
	// 棋子半斤
	private int pieceRadius;
	// 记录落子情况
	private List<Piece> downPiece = new ArrayList<>();
	// 用于翻转棋子颜色的标志位
	private boolean colorFlag;
	// 游戏结束标志位
	private boolean gameOver = false;
	// 储存读取到的棋谱数据
	private List<Piece> savedPieces = new ArrayList<>();
	// 存储读取棋谱时的步数
	private int step;

	private Stage stage = this;

	public SingleModeStage() {
		this.margin = 50;
		this.size = 40;
		this.cellCount = 15;
		this.buttonArea = 60;
		this.pieceRadius = 15;
		this.colorFlag = false;

		// 为窗体设置标题
		setTitle("蜗牛五子棋");
		// 设置窗体大小不可调整
		setResizable(false);
		// 创建面板
		Pane pane = new Pane();
		// 设置背景颜色
		pane.setBackground(new Background(new BackgroundFill(Color.BLANCHEDALMOND, null, null)));
		// 调用绘制棋盘的方法
		drawChessBoard(pane);
		// 面板实现鼠标事件监听
		pane.setOnMouseClicked(new EventHandler<MouseEvent>() {

			@Override
			public void handle(MouseEvent event) {

				if (gameOver == true) {
					return;
				}
				// 限制落子区域
				if (event.getX() <= margin - size / 2 || event.getX() >= margin + cellCount * size + size / 2) {
					return;
				}
				// 限制落子区域
				if (event.getY() <= margin - size / 2 || event.getY() >= margin + cellCount * size + size / 2) {
					return;
				}

				int pieceX = (int) (((event.getX() + size / 2) - margin) / size);
				int pieceY = (int) (((event.getY() + size / 2) - margin) / size);
				drawChess(pieceX, pieceY, pane);
				
		

				

			}

		});
		
		this.setOnCloseRequest(new EventHandler<WindowEvent>() {
            @Override
            public void handle(WindowEvent event) {
                System.exit(0);
            }
        });

		// 创建一个场景对象
		Scene scene = new Scene(pane, margin * 2 + cellCount * size, margin * 2 + cellCount * size + buttonArea);// 控制窗体尺寸
		// 将场景添加到窗体上
		setScene(scene);

		// 将线条添加到面板
		show();
	}

	public void drawChess(int pieceX, int pieceY, Pane pane) {
		// 检查是否落子 true为已落子
		for (Piece piece : downPiece) {
			if (piece.getX() == pieceX && piece.getY() == pieceY) {
				return;
			}
		}

		// 创建圆对象
		Circle piece = new Circle();
		piece.setRadius(pieceRadius);

		// 设置背景颜色 根据标志位转换
		if (this.colorFlag) {
			piece.setFill(Color.BLACK);
			Piece pieceData = new Piece(pieceX, pieceY, Color.BLACK);
			downPiece.add(pieceData);
		} else {
			piece.setFill(Color.WHITE);
			Piece pieceData = new Piece(pieceX, pieceY, Color.WHITE);
			downPiece.add(pieceData);
		}

		if (downPiece.size() == 16 * 16) {
			gameOver = true;
			Alert alert = new Alert(AlertType.INFORMATION);
			alert.setContentText("平局");
			alert.show();
			return;
		}

		piece.setCenterX(pieceX * this.size + this.margin);
		piece.setCenterY(pieceY * this.size + this.margin);
		this.colorFlag = !this.colorFlag;
		pane.getChildren().add(piece);
		
		// 输赢判断
		// 存储棋子颜色状态
		Color color = null;
		if (colorFlag) {
			color = Color.WHITE;
		} else {
			color = Color.BLACK;
		}
		// 水平方向判断
		// 向左判断
		int pieceCount = 1;
		for (int x = pieceX - 1; x > pieceX - 5 && x >= 0; x--) {
			if (checkPiece(x, pieceY, color)) {
				pieceCount++;
			} else {
				break;
			}

		}

		for (int x = pieceX + 1; x < pieceX + 5 && x < 16; x++) {
			if (checkPiece(x, pieceY, color)) {
				pieceCount++;
			} else {
				break;
			}
		}

		printResult(pieceCount);

		// 垂直方向判断
		pieceCount = 1;
		// 向上判断
		for (int y = pieceY - 1; y > pieceY - 5 && y >= 0; y--) {
			if (checkPiece(pieceX, y, color)) {
				pieceCount++;
			} else {
				break;
			}
		}

		// 向下判断
		for (int y = pieceY + 1; y < pieceY + 5 && y < 16; y++) {
			if (checkPiece(pieceX, y, color)) {
				pieceCount++;
			} else {
				break;
			}
		}
		printResult(pieceCount);

		pieceCount = 1;
		// 左下
		int x = pieceX - 1;
		int y = pieceY + 1;
		while (x > pieceX - 5 && y < pieceY + 5 && x >= 0 && y <= 15) {
			if (checkPiece(x, y, color)) {
				pieceCount++;
			} else {
				break;
			}
			x--;
			y++;
		}
		// 右上
		x = pieceX + 1;
		y = pieceY - 1;
		while (x < pieceX + 5 && y > pieceY - 5 && y >= 0 && x <= 15) {
			if (checkPiece(x, y, color)) {
				pieceCount++;
			} else {
				break;
			}
			x++;
			y--;
		}
		printResult(pieceCount);

		pieceCount = 1;
		// 左上
		x = pieceX - 1;
		y = pieceY - 1;
		while (x > pieceX - 5 && y > pieceY - 5 && y >= 0 && x >= 0) {
			if (checkPiece(x, y, color)) {
				pieceCount++;
			} else {
				break;
			}
			x--;
			y--;
		}
		// 右下
		x = pieceX + 1;
		y = pieceY + 1;
		while (x < pieceX + 5 && y < pieceY + 5 && y <= 15 && x <= 15) {
			if (checkPiece(x, y, color)) {
				pieceCount++;
			} else {
				break;
			}
			x++;
			y++;
		}

		printResult(pieceCount);

	}

	// 找是否有一个指定位置的棋子
	public boolean checkPiece(int pieceX, int pieceY, Color color) {
		for (Piece piece : downPiece) {
			if (piece.getX() == pieceX && piece.getY() == pieceY && piece.getColor().equals(color)) {
				return true;
			}
		}
		return false;
	}

	// 在打谱模式下绘制棋子
	public void hisDrawChess(int pieceX, int pieceY, Paint value, Pane pane) {
		// 创建圆对象
		Circle piece = new Circle();
		piece.setRadius(pieceRadius);
		piece.setFill(value);
		piece.setCenterX(pieceX * this.size + this.margin);
		piece.setCenterY(pieceY * this.size + this.margin);
		pane.getChildren().add(piece);

	}

	public void printResult(int pieceCount) {
		if (pieceCount >= 5) {
			gameOver = true;
			if (colorFlag) {
				Alert alert = new Alert(AlertType.INFORMATION);
				alert.setContentText("白方胜利");
				alert.show();
				return;
			} else {
				Alert alert = new Alert(AlertType.INFORMATION);
				alert.setContentText("黑方胜利");
				alert.show();
				return;
			}
		}
	}

	public void drawChessBoard(Pane pane) {
		// 画出横线
		for (int i = 0; i < cellCount + 1; i++) {
			// 创建线条
			Line line = new Line(margin, margin + i * size, margin + cellCount * size, margin + i * size);
			// 将线条添加到面板
			pane.getChildren().add(line);
		}
		// 画出竖线
		for (int i = 0; i < cellCount + 1; i++) {
			// 创建线条
			Line line = new Line(margin + i * size, margin, margin + i * size, margin + cellCount * size);
			// 将线条添加到面板
			pane.getChildren().add(line);
		}

		// 创建新局按钮对象
		Button btnNew = new Button("新局");
		btnNew.setPrefSize(80, 50);
		btnNew.setLayoutX(50);
		btnNew.setLayoutY(670);
		pane.getChildren().add(btnNew);

		// 新局执行
		btnNew.setOnMouseClicked(new EventHandler<Event>() {

			@Override
			public void handle(Event event) {
				// 清空棋子节点
				pane.getChildren().removeIf(n -> n instanceof Circle);
				// 清空棋子数据
				downPiece.clear();

				colorFlag = false;
				gameOver = false;
			}
		});

		// 创建保存棋谱按钮对象
		Button btnSave = new Button("保存棋谱");
		btnSave.setPrefSize(80, 50);
		btnSave.setLayoutX(170);
		btnSave.setLayoutY(670);
		pane.getChildren().add(btnSave);
		// 保存棋谱执行
		btnSave.setOnMouseClicked(new EventHandler<Event>() {

			public void handle(Event event) {
				if (!gameOver) {
					Alert alert = new Alert(AlertType.INFORMATION);
					alert.setContentText("棋局未结束，无法保存");
					alert.show();
					return;
				}
				FileChooser fileChooser = new FileChooser();
				File file = fileChooser.showSaveDialog(stage);
				// 从List中读取棋子数据，将其写入file中，后缀为csv
				if (file == null) {
					return;
				}
				try {
					// 创建字符流
					BufferedWriter writer = new BufferedWriter(new FileWriter(file));
					for (Piece piece : downPiece) {
						String colorstr = null;
						if (piece.getColor().equals(Color.WHITE)) {
							colorstr = "white";
						} else if (piece.getColor().equals(Color.BLACK)) {
							colorstr = "black";
						}
						writer.write(piece.getX() + "," + piece.getY() + "," + colorstr);
						writer.newLine();
					}

					writer.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

		});

		// 创建棋谱按钮对象
		Button btnLoad = new Button("读取棋谱");
		btnLoad.setPrefSize(80, 50);
		btnLoad.setLayoutX(290);
		btnLoad.setLayoutY(670);
		pane.getChildren().add(btnLoad);
		// 读取棋谱执行
		btnLoad.setOnMouseClicked(new EventHandler<Event>() {

			@Override
			public void handle(Event event) {

				try {
					FileChooser fileChooser = new FileChooser();
					File file = fileChooser.showOpenDialog(stage);
					// 如果没有点开文件结束方法
					if (file == null) {
						return;
					}
					step = 0;
					// 清空棋子节点
					pane.getChildren().removeIf(n -> n instanceof Circle);
					// 清空棋子数据
					downPiece.clear();
					colorFlag = false;
					gameOver = true;

					Button preBtn = new Button("<");
					preBtn.setPrefSize(32, 32);
					preBtn.setLayoutX(660);
					preBtn.setLayoutY(270);
					pane.getChildren().add(preBtn);
					preBtn.setOnMouseClicked(new EventHandler<Event>() {
						// 返回上一步棋
						@Override
						public void handle(Event event) {
							if (step > 0) {
								pane.getChildren().remove(pane.getChildren().size() - 1);
								step--;
							}
						}

					});

					Button nextBtn = new Button(">");
					nextBtn.setPrefSize(32, 32);
					nextBtn.setLayoutX(660);
					nextBtn.setLayoutY(310);
					pane.getChildren().add(nextBtn);
					nextBtn.setOnMouseClicked(new EventHandler<Event>() {
						// 绘制下一步棋
						@Override
						public void handle(Event event) {
							if (step < savedPieces.size()) {
								Piece nowStep = savedPieces.get(step++);
								hisDrawChess(nowStep.getX(), nowStep.getY(), nowStep.getColor(), pane);
							}
						}
					});

					Button ExitBtn = new Button("x");
					ExitBtn.setPrefSize(32, 32);
					ExitBtn.setLayoutX(660);
					ExitBtn.setLayoutY(350);
					pane.getChildren().add(ExitBtn);
					ExitBtn.setOnMouseClicked(new EventHandler<Event>() {
						// 绘制下一步棋
						@Override
						public void handle(Event event) {
							pane.getChildren().remove(preBtn);
							pane.getChildren().remove(nextBtn);
							pane.getChildren().remove(ExitBtn);
							// 清空棋子节点
							pane.getChildren().removeIf(n -> n instanceof Circle);
							// 清空棋子数据
							downPiece.clear();
							colorFlag = false;
							gameOver = false;
						}
					});

					BufferedReader reader = new BufferedReader(new FileReader(file));
					String content = null;
					while ((content = reader.readLine()) != null) {
						String[] pieceDatas = content.split(",");
						Piece piece = new Piece();
						piece.setX(Integer.parseInt(pieceDatas[0]));
						piece.setY(Integer.parseInt(pieceDatas[1]));
						if (pieceDatas[2].equals("white")) {
							piece.setColor(Color.WHITE);
						} else {
							piece.setColor(Color.BLACK);
						}
						savedPieces.add(piece);
					}
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}

			}

		});

		// 创建悔棋按钮对象
		Button btnRegret = new Button("悔棋");
		btnRegret.setPrefSize(80, 50);
		btnRegret.setLayoutX(410);
		btnRegret.setLayoutY(670);
		pane.getChildren().add(btnRegret);
		// 悔棋执行
		btnRegret.setOnMouseClicked(e -> {
			// 当有棋子时才能悔棋
			if (downPiece.size() > 0) {
				downPiece.remove(downPiece.size() - 1);
				pane.getChildren().remove(pane.getChildren().size() - 1);
				colorFlag = !colorFlag;
			}
		});

		// 创建退出按钮对象
		Button btnExit = new Button("退出");
		btnExit.setPrefSize(80, 50);
		btnExit.setLayoutX(530);
		btnExit.setLayoutY(670);
		pane.getChildren().add(btnExit);
		// 退出执行
		btnExit.setOnMouseClicked(e -> {
			Alert alert = new Alert(AlertType.CONFIRMATION);
			// 设置提示框内容
			alert.setContentText("您确认退出吗?");
			// 设置提示框标题
			alert.setTitle("退出提示");
			// 展示弹框
			Optional<ButtonType> r = alert.showAndWait();
			if (r.get() == ButtonType.OK) {
				System.exit(0);
			}
		});

	}
}
